package com.sc.nft.controller;

import cn.hutool.core.util.StrUtil;
import com.sc.nft.controller.request.GetSmsNewCodeRequest;
import com.sc.nft.dao.FilterIncomeListDao;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.CheckParameterService;
import com.sc.nft.service.SmsCodeRecordService;
import com.sc.nft.service.StaticDataService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import com.sc.nft.util.RedisUtil;
import com.sc.nft.util.TokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 内部API服务（微服务间横向调用）
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/internal")
@Api(tags = "内部API服务")
public class InternalApiController {

    private final StaticDataService staticDataService;
    private final CheckParameterService checkParameterService;
    private final RedisUtil redisUtil;
    private final Redisson redisson;
    private final SmsCodeRecordService smsCodeRecordService;

    /**
     * 短信验证码验证API（过渡使用，后续将迁移到edge服务中），短信发送接口见：StaticDataController#sendRegisteSmsNew(GetSmsNewCodeRequest)
     *
     * @param smsId   短信模板ID
     * @param mobile  手机号
     * @param code    验证码
     * @param bizCode 业务代码，参考：com.sc.nft.enums.SendSMSEnum
     * @return Pair(code, message)，参考：com.sc.nft.sup.ErrorCode，实际可选值 [SUCCESS, VERIFICATION_ERROR, ACCOUNT_IS_INCORRECT, CAPTCHA_EXPIRE, VERIFICATION_ERROR]
     * @see InternalApiController#sendRegisteSmsNew(GetSmsNewCodeRequest)
     */
    @PostMapping(value = "/verify", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "短信验证码验证", notes = "短信验证码验证", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<?> verify(@RequestParam("smsId") long smsId,
                            @RequestParam("mobile") String mobile,
                            @RequestParam("code") String code,
                            @RequestParam("bizCode") Integer bizCode) {
        try {
            checkParameterService.CheckVerificationcode(mobile, smsId, code, bizCode);
            return Result.success(ErrorCode.SUCCESS);
        } catch (GlobalRunTimeException e) {
            log.warn("短信验证码验证失败 mobile: {}, code: {}, smsId: {}, bizCode: {}, error: {}", mobile, code, smsId, bizCode, e.getMessage());
            return Result.fail(e.getErrorCode());
        }
    }

    /**
     * 发送验证码
     * @param
     * @return
     */
    @PostMapping(value = "/sendMsg", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<?> send(@RequestParam("type") Integer  type,
                          @RequestParam("mobile") String mobile,
                          @RequestParam("verifyCode") String verifyCode) {
        if (type == 1) {

            if (StrUtil.startWithAny(mobile, "192", "162", "165", "167", "170", "171")) {
                return Result.success();
            }
        }
        if (type != 13) {
            String code = String.valueOf(redisUtil.get(TokenUtil.getRegisterValidateCode(mobile, type)));

            if (StrUtil.equals(code, "null") || !StrUtil.equals(code, verifyCode)) {
                return Result.fail(ErrorCode.VERIFICATION_ERROR);
            }
        }

        String key = StrUtil.format("{}{}", RedisKeyEnum.MESSAGE_AUTHENTICATION_CODE.getKey(), mobile);
        log.info("获取注册验证码(新) key:{}", key);
        RLock lock = redisson.getLock(key);
        HashMap<String, String> map = null;
        boolean b = lock.tryLock();
        try {
            log.info("获取注册验证码(新) 锁获取:{}", b);
            if (!b) {
                throw new GlobalRunTimeException("验证码已发送");
            }
            map = smsCodeRecordService.sendRegisteSms(mobile,
                    type,
                    null);
        } catch (IllegalMonitorStateException e) {
            throw new GlobalRunTimeException("验证码已发送");
        } finally {
            //删除验证码
            redisUtil.del(TokenUtil.getRegisterValidateCode(mobile, type));
            if (b) {
                lock.unlock();
            }
        }
        return Result.success(map);
    }

    @PostMapping(value = "/fetch", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "静态数据查询", notes = "按需查询静态数据", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result<Map<String, String>> fetch(@RequestBody List<String> types) {
        return Result.success(staticDataService.listByTypes(types));
    }

}